﻿using EnvDTE;
using Microsoft.VisualStudio.SharePoint;
using Microsoft.VisualStudio.TemplateWizard;
using System;
using System.Collections.Generic;
using System.IO;

namespace SPTotalAutomationToolkit.SP2013IntranetProjectTemplate.Wizard
{
    public class ProjectWizard : IWizard
    {
        private WizardWindow wizardUI;
        private DTE dteObject;
        private ProjectWizardModel presentationModel;
        private ProjectSigningManager signingManager;
        
        public static Dictionary<string, string> GlobalDictionary;  // Used to pass values from Root Project Template Wizard to the Child implementations
        public static Dictionary<string, string> ProjectGuids; // Used to keep a list of all the GUIDs needed by the child projects
        public static bool IsSandboxed;
        public static string SiteUrlForDebugging;

        public ProjectWizard()
        {
            signingManager = new ProjectSigningManager();
        }

        public void RunStarted(object automationObject, Dictionary<string, string> replacementsDictionary, WizardRunKind runKind, object[] customParams)
        {
            GlobalDictionary = new Dictionary<string, string>();
            ProjectGuids = new Dictionary<string, string>();

            dteObject = automationObject as DTE;
            presentationModel = new ProjectWizardModel(dteObject, false);

            // Initialize values in the presentation model from data entered into the new project dialog box
            var solutionNameArray = replacementsDictionary["$safeprojectname$"].Split('.');
            presentationModel.ClientName = solutionNameArray[0];
            
            if (solutionNameArray.Length > 1)
            {
                presentationModel.ProjectName = solutionNameArray[1];
            }

            if (!presentationModel.ProjectService.IsSharePointInstalled)
            {
                string errorString = "A SharePoint server is not installed on this computer. A SharePoint server " + "must be installed to work with SharePoint projects.";
                System.Windows.MessageBox.Show(errorString, "SharePoint Not Installed", System.Windows.MessageBoxButton.OK, System.Windows.MessageBoxImage.Error);
                throw new WizardCancelledException(errorString);
            }

            wizardUI = new WizardWindow(presentationModel);
            Nullable<bool> dialogCompleted = wizardUI.ShowModal();

            if (dialogCompleted == true)
            {
                // Set the public variables used for the VS project settings
                IsSandboxed = presentationModel.IsSandboxed;
                SiteUrlForDebugging = presentationModel.SiteUrlForDebugging;

                if (presentationModel.WriteIntranetHostFileEntry == true)
                {
                    // Write an entry for the new site into the host file
                    WriteHostsFile("127.0.0.1", presentationModel.IntranetWebAppHostHeaderForDev);
                }

                if (presentationModel.WritePeopleHostFileEntry == true)
                {
                    // Write an entry for the new site into the host file
                    WriteHostsFile("127.0.0.1", presentationModel.PeopleWebAppHostHeaderForDev);
                }
                
                // Generate unique GUIDs for use throughout the project
                GenerateGuids();

                // Replace the project name with values from the dialog
                replacementsDictionary["$safeprojectname$"] = presentationModel.ClientNameWithoutSpaces + "." + presentationModel.ProjectNameWithoutSpaces;

                
                // Add the user entered values into the Global Dictionary to be passed to the child projects
                GlobalDictionary.Add("$solutionName$", replacementsDictionary["$safeprojectname$"]);
                GlobalDictionary.Add("$clientName$", presentationModel.ClientName);
                GlobalDictionary.Add("$clientNameWithoutSpaces$", presentationModel.ClientNameWithoutSpaces);
                GlobalDictionary.Add("$projectName$", presentationModel.ProjectName);
                GlobalDictionary.Add("$projectNameWithoutSpaces$", presentationModel.ProjectNameWithoutSpaces);
                GlobalDictionary.Add("$intranetWebAppHostHeaderForDev$", presentationModel.IntranetWebAppHostHeaderForDev);
                GlobalDictionary.Add("$intranetWebAppPortForDev$", presentationModel.IntranetWebAppPortForDev);
                GlobalDictionary.Add("$peopleWebAppHostHeaderForDev$", presentationModel.PeopleWebAppHostHeaderForDev);
                GlobalDictionary.Add("$peopleWebAppPortForDev$", presentationModel.PeopleWebAppPortForDev);
                GlobalDictionary.Add("$projectIsSandboxed$", presentationModel.IsSandboxed.ToString());
                GlobalDictionary.Add("$useHostNamedSiteCollections$", presentationModel.UseHostNamedSiteCollections.ToString());

                replacementsDictionary.Add("$clientName$", presentationModel.ClientName);
                replacementsDictionary.Add("$clientNameWithoutSpaces$", presentationModel.ClientNameWithoutSpaces);
                replacementsDictionary.Add("$projectName$", presentationModel.ProjectName);
                replacementsDictionary.Add("$projectNameWithoutSpaces$", presentationModel.ProjectNameWithoutSpaces);
                replacementsDictionary.Add("$intranetWebAppHostHeaderForDev$", presentationModel.IntranetWebAppHostHeaderForDev);
                replacementsDictionary.Add("$intranetWebAppPortForDev$", presentationModel.IntranetWebAppPortForDev);
                replacementsDictionary.Add("$peopleWebAppHostHeaderForDev$", presentationModel.PeopleWebAppHostHeaderForDev);
                replacementsDictionary.Add("$peopleWebAppPortForDev$", presentationModel.PeopleWebAppPortForDev);
                replacementsDictionary.Add("$projectIsSandboxed$", presentationModel.IsSandboxed.ToString());
                replacementsDictionary.Add("$useHostNamedSiteCollections$", presentationModel.UseHostNamedSiteCollections.ToString());

                if (presentationModel.UseHostNamedSiteCollections)
                {
                    GlobalDictionary.Add("$serverNameForDevWithFQDN$", presentationModel.ServerNameForDevWithFQDN);
                    GlobalDictionary.Add("$serverPortForDev$", presentationModel.ServerPortForDev);

                    replacementsDictionary.Add("$serverNameForDevWithFQDN$", presentationModel.ServerNameForDevWithFQDN);
                    replacementsDictionary.Add("$serverPortForDev$", presentationModel.ServerPortForDev);
                }
            }
            else
            {
                throw new WizardCancelledException();
            }
        }

        public void ProjectFinishedGenerating(Project project)
        {
        }

        // Always return true; this IWizard implementation throws a WizardCancelledException
        // that is handled by Visual Studio if the user cancels the wizard.
        public bool ShouldAddProjectItem(string filePath)
        {
            return true;
        }

        public void BeforeOpeningFile(ProjectItem projectItem)
        {
        }

        public void ProjectItemFinishedGenerating(ProjectItem projectItem)
        {
        }

        public void RunFinished()
        {
        }

        /// <summary>
        /// This function generates new GUIDs and adds them into the Global Dictionary for use as 
        /// replacement parameters in child projects
        /// </summary>
        private static void GenerateGuids()
        {
            #region Automation Project GUIDs
            // -----------------------
            // Automation Project
            // -----------------------

            // SharePoint Project and Package GUIDs
            ProjectGuids.Add("$Guid_ProjectID_Automation$", "D");
            ProjectGuids.Add("$Guid_PackageID_Automation$", "D");

            // SharePoint Feature GUIDs
            ProjectGuids.Add("$Guid_Feature_Automation_RootSiteTemplate$", "D");
            ProjectGuids.Add("$Guid_FeatureRecieverClass_Automation_RootSiteTemplate$", "D");

            #endregion

            #region Utilities Project GUIDs
            // -----------------------
            // Utilities Project
            // -----------------------

            // SharePoint Project and Package GUIDs
            ProjectGuids.Add("$Guid_ProjectID_Utilities$", "D");

            #endregion

            #region Custom Assemblies Project GUIDs
            // -----------------------
            // Custom Assemblies Project
            // -----------------------

            // SharePoint Project and Package GUIDs
            ProjectGuids.Add("$Guid_ProjectID_CustomAssemblies$", "D");
            ProjectGuids.Add("$Guid_PackageID_CustomAssemblies$", "D");

            // SharePoint Feature GUIDs
            ProjectGuids.Add("$Guid_Feature_CustomAssemblies_Install$", "D");

            #endregion

            #region Content Type Project GUIDs
            // -----------------------
            // Content Types Project
            // -----------------------

            // SharePoint Project and Package GUIDs
            ProjectGuids.Add("$Guid_ProjectID_ContentTypes$", "D");
            ProjectGuids.Add("$Guid_PackageID_ContentTypes$", "D");

            // SharePoint Feature GUIDs
            ProjectGuids.Add("$Guid_Feature_ContentTypes_DeployAndPublish$", "D");
            ProjectGuids.Add("$Guid_FeatureRecieverClass_Automation_DeployAndPublish$", "D");

            // VS Project Item GUIDs
            ProjectGuids.Add("$Guid_ProjectItem_ContentTypes_CustomArticlePage$", "D");
            ProjectGuids.Add("$Guid_ProjectItem_ContentTypes_CustomPage$", "D");
            ProjectGuids.Add("$Guid_ProjectItem_ContentTypes_CustomSitePage$", "D");
            ProjectGuids.Add("$Guid_ProjectItem_ContentTypes_CustomWelcomePage$", "D");
            ProjectGuids.Add("$Guid_ProjectItem_Field_ApprovedForHomePage$", "D");
            ProjectGuids.Add("$Guid_ProjectItem_Field_ApprovedForHomePageBanner$", "D");
            ProjectGuids.Add("$Guid_ProjectItem_Field_BannerImage$", "D");
            ProjectGuids.Add("$Guid_ProjectItem_Field_BannerSubtitle$", "D");
            ProjectGuids.Add("$Guid_ProjectItem_Field_BannerTitle$", "D");
            ProjectGuids.Add("$Guid_ProjectItem_Field_HomePageBannerBeginDate$", "D");
            ProjectGuids.Add("$Guid_ProjectItem_Field_HomePageBannerEndDate$", "D");
            ProjectGuids.Add("$Guid_ProjectItem_Field_HomePageBeginDate$", "D");
            ProjectGuids.Add("$Guid_ProjectItem_Field_HomePageEndDate$", "D");
            ProjectGuids.Add("$Guid_ProjectItem_Field_Synopsis$", "D");

            #endregion

            #region Infrastructure Project GUIDs
            // -----------------------
            // Infrastructure Project
            // -----------------------

            // SharePoint Project and Package GUIDs
            ProjectGuids.Add("$Guid_ProjectID_Infrastructure$", "D");
            ProjectGuids.Add("$Guid_PackageID_Infrastructure$", "D");

            // SharePoint Feature GUIDs
            ProjectGuids.Add("$Guid_Feature_Infrastructure_Install$", "D");
            ProjectGuids.Add("$Guid_FeatureRecieverClass_Automation_Install$", "D");
            
            // VS Project Item GUIDs
            ProjectGuids.Add("$Guid_ProjectItem_Infrastructure_ListTemplatesModule$", "D");
            ProjectGuids.Add("$Guid_ProjectItem_Infrastructure_MasterPagesModule$", "D");
            ProjectGuids.Add("$Guid_ProjectItem_Infrastructure_PublishingImagesModule$", "D");
            ProjectGuids.Add("$Guid_ProjectItem_Infrastructure_StyleLibraryModule$", "D");
            ProjectGuids.Add("$Guid_ProjectItem_Infrastructure_WebPartsModule$", "D");

            #endregion

            #region Deployment Project GUIDs
            // -----------------------
            // Deployment Project
            // -----------------------

            // SharePoint Project and Package GUIDs
            ProjectGuids.Add("$Guid_ProjectID_Deployment$", "D");

            #endregion
            
            #region Cross-Project Item GUIDs
            // -----------------------
            // Cross-Project Item GUIDs
            // -----------------------

            // Site Columns (Fields)
            ProjectGuids.Add("$Guid_Fields_ApprovedForHomePage$", "D");
            ProjectGuids.Add("$Guid_Fields_ApprovedForHomePageBanner$", "D");
            ProjectGuids.Add("$Guid_Fields_BannerImage$", "D");
            ProjectGuids.Add("$Guid_Fields_BannerSubtitle$", "D");
            ProjectGuids.Add("$Guid_Fields_BannerTitle$", "D");
            ProjectGuids.Add("$Guid_Fields_HomePageBannerBeginDate$", "D");
            ProjectGuids.Add("$Guid_Fields_HomePageBannerEndDate$", "D");
            ProjectGuids.Add("$Guid_Fields_HomePageBeginDate$", "D");
            ProjectGuids.Add("$Guid_Fields_HomePageEndDate$", "D");
            ProjectGuids.Add("$Guid_Fields_Synopsis$", "D");

            // Content Types
            ProjectGuids.Add("$Guid_ContentType_CustomArticlePage$", "N");
            ProjectGuids.Add("$Guid_ContentType_CustomPage$", "N");
            ProjectGuids.Add("$Guid_ContentType_CustomSitePage$", "N");
            ProjectGuids.Add("$Guid_ContentType_CustomWelcomePage$", "N");

            // Managed Metadata Terms
            ProjectGuids.Add("$Guid_Terms_ArticleTypes$", "D");
            ProjectGuids.Add("$Guid_Terms_ArticleTypes_General$", "D");
            ProjectGuids.Add("$Guid_Terms_ArticleTypes_LocalInterest$", "D");
            ProjectGuids.Add("$Guid_Terms_ArticleTypes_FacilityBulletins$", "D");
            ProjectGuids.Add("$Guid_Terms_ArticleTypes_TechBulletins$", "D");
            ProjectGuids.Add("$Guid_Terms_ArticleTypes_OrgUpdates$", "D");
            ProjectGuids.Add("$Guid_Terms_ArticleTypes_EmployeeNews$", "D");
            ProjectGuids.Add("$Guid_Terms_NewsSiteNav$", "D");
            ProjectGuids.Add("$Guid_Terms_NewsSiteNav_Home$", "D");

            #endregion


            foreach (var projectGuid in ProjectGuids)
            {
                GlobalDictionary.Add(projectGuid.Key, Guid.NewGuid().ToString(projectGuid.Value));
            }
        }

        private static void WriteHostsFile(string ipAddress, string Fqdn)
        {
            using (StreamWriter w = File.AppendText(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.System), "drivers/etc/hosts")))
            {
                w.WriteLine("");
                w.WriteLine(ipAddress + "    " + Fqdn);
            }
        }

        public static string ExtractDomainNameFromURL(string Url)
        {
            if (Url.Contains(@"://"))
                Url = Url.Split(new string[] { "://" }, 2, StringSplitOptions.None)[1];

            return Url.Split('/')[0];
        }    
    }
}